﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Ninject;
using Timetable.Base.Interfaces.Services;
using System.Net.Http;
using System.Net;
using Timetable.Utils.Exceptions;
using Timetable.Base.Entities;
using Timetable.Base.Interfaces.Services.DataServices;

namespace Timetable.Site.Controllers.Api
{
    public abstract class BaseApiController<T> : System.Web.Http.ApiController, IBaseController where T: BaseEntity
    {
        [Inject]
        public IAuthenticateService AuthenticateService { get; set; }

        [Inject]
        public IRegistrationService RegistrationService { get; set; }

        [Inject]
        public IDataService<T> DataService { get; set; }

        protected HttpResponseMessage Response;

        protected HttpResponseMessage CreateResponse<T>(Func<T> func)
        {
            try
            {
                var result = func();

                Response = Request.CreateResponse<T>(HttpStatusCode.OK, result);
            }
            catch (EntityNotFoundException ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.NotFound, ex);
            }
            catch (Exception ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.InternalServerError, ex);
            }

            return Response;
        }

        protected HttpResponseMessage CreateResponse<T1, T2>(Func<T1, T2> func, T1 arg)
        {
            try
            {
                var result = func(arg);

                Response = Request.CreateResponse<T2>(HttpStatusCode.OK, result);
            }
            catch (EntityNotFoundException ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.NotFound, ex);
            }
            catch (Exception ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.InternalServerError, ex);
            }

            return Response;
        }

        protected HttpResponseMessage CreateResponse<T1, T2, T3>(Func<T1, T2, T3> func, T1 arg1, T2 arg2)
        {
            try
            {
                var result = func(arg1, arg2);

                Response = Request.CreateResponse(HttpStatusCode.OK, result);
            }
            catch (EntityNotFoundException ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.NotFound, ex.ToString());
            }
            catch (Exception ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.InternalServerError, ex);
            }

            return Response;
        }

        protected HttpResponseMessage CreateResponse<T1, T2, T3, T4, T5>(Func<T1, T2, T3, T4, T5> func, T1 arg1, T2 arg2, T3 arg3, T4 arg4)
        {
            try
            {
                var result = func(arg1, arg2, arg3, arg4);

                Response = Request.CreateResponse(HttpStatusCode.OK, result);
            }
            catch (EntityNotFoundException ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.NotFound, ex.ToString());
            }
            catch (Exception ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.InternalServerError, ex);
            }

            return Response;
        }

        protected HttpResponseMessage CreateResponse(Action action)
        {
            try
            {
                action();

                Response = Request.CreateResponse(HttpStatusCode.OK);
            }
            catch (EntityNotFoundException ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.NotFound, ex);
            }
            catch (Exception ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.InternalServerError, ex);
            }

            return Response;
        }

        protected HttpResponseMessage CreateResponse<T>(Action<T> action, T arg)
        {
            try
            {
                action(arg);

                Response = Request.CreateResponse(HttpStatusCode.OK);
            }
            catch (EntityNotFoundException ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.NotFound, ex);
            }
            catch (Exception ex)
            {
                Response = Request.CreateResponse(HttpStatusCode.InternalServerError, ex);
            }

            return Response;
        }
    }
}
